#include "D3D12DescHeapManager.h"



D3D12DescHeapManager::D3D12DescHeapManager()
{
}


D3D12DescHeapManager::~D3D12DescHeapManager()
{
}

_hr D3D12DescHeapManager::SetUp(ID3D12Device* pDevice, UINT numRtvDesc, UINT numDestDesc, UINT numCsvDesc)
{
	_hr errorCode = _OK;

	D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
	heapDesc.NumDescriptors = numRtvDesc;
	heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
	heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	errorCode = pDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&m_rtvHeap));
	_ERROR_CHECK(errorCode)

	m_rtvDescSize = pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
	m_rtvHeapSize = numRtvDesc;

	heapDesc.NumDescriptors = numDestDesc;
	heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
	heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	errorCode = pDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&m_dstHeap));
	_ERROR_CHECK(errorCode)

	m_dstDescSize = pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
	m_dstHeapSize = numDestDesc;

	heapDesc.NumDescriptors = numCsvDesc;
	heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
	heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
	errorCode = pDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&m_csvHeap));
	_ERROR_CHECK(errorCode)

	m_csvDescSize = pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
	m_csvHeapSize = numCsvDesc;
	
	return _OK;
}

D3D12_CPU_DESCRIPTOR_HANDLE D3D12DescHeapManager::GetDescHandleCPU(D3D12_DESCRIPTOR_HEAP_TYPE type, UINT offset)
{
	ComPtr<ID3D12DescriptorHeap> heap;
	UINT descSize;
	switch (type)
	{
	case D3D12_DESCRIPTOR_HEAP_TYPE_RTV:
		m_rtvHeap.As(&heap);
		descSize = m_rtvDescSize;
		break;
	case D3D12_DESCRIPTOR_HEAP_TYPE_DSV:
		m_dstHeap.As(&heap);
		descSize = m_dstDescSize;
		break;
	case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
		m_csvHeap.As(&heap);
		descSize = m_csvDescSize;
		break;
	default:
		break;
	}
	D3D12_CPU_DESCRIPTOR_HANDLE result = heap->GetCPUDescriptorHandleForHeapStart();
	result.ptr += offset*descSize;
	return  result;
}

D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescHeapManager::GetDescHandleGPU(D3D12_DESCRIPTOR_HEAP_TYPE type, UINT offset)
{
	ComPtr<ID3D12DescriptorHeap> heap;
	UINT descSize;
	switch (type)
	{
	case D3D12_DESCRIPTOR_HEAP_TYPE_RTV:
		m_rtvHeap.As(&heap);
		descSize = m_rtvDescSize;
		break;
	case D3D12_DESCRIPTOR_HEAP_TYPE_DSV:
		m_dstHeap.As(&heap);
		descSize = m_dstDescSize;
		break;
	case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
		m_csvHeap.As(&heap);
		descSize = m_csvDescSize;
		break;
	default:
		break;
	}
	D3D12_GPU_DESCRIPTOR_HANDLE result = heap->GetGPUDescriptorHandleForHeapStart();
	result.ptr += offset*descSize;
	return  result;
}

UINT D3D12DescHeapManager::AlloctDescHandle(D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, D3D12_GPU_DESCRIPTOR_HANDLE* pGpuHandleStart, D3D12_CPU_DESCRIPTOR_HANDLE* pCpuHandleStart)
{
	UINT  curPos;
	UINT  maxSize;
	UINT* mCurPos;
	switch (type)
	{
	case D3D12_DESCRIPTOR_HEAP_TYPE_RTV:
		curPos = m_rtvCurrentPos;
		maxSize = m_rtvDescSize;
		mCurPos = &m_rtvCurrentPos;
		break;
	case D3D12_DESCRIPTOR_HEAP_TYPE_DSV:
		curPos = m_dstCurrentPos;
		maxSize = m_dstDescSize;
		mCurPos = &m_dstCurrentPos;
		break;
	case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
		curPos = m_csvCurrentPos;
		maxSize = m_csvDescSize;
		mCurPos = &m_csvCurrentPos;
		break;
	default:
		curPos = m_rtvCurrentPos;
		maxSize = m_rtvDescSize;
		mCurPos = &m_rtvCurrentPos;
		break;
	}
	if (curPos + num >= maxSize)
	{
		return -1; // out of boundary
	}
	*mCurPos = curPos + num;
	//*pCpuHandleStart = GetDescHandleCPU(type, curPos);
	//*pGpuHandleStart = GetDescHandleGPU(type, curPos);

	return curPos;
}
